# -*- coding: utf-8 -*-
# keywords_heat.py
# Created by Hardy on 24th, Feb
# Copyright 2017 杭州网川教育科技有限公司. All rights reserved.

from querier.esquerier import ElasticSearchQuerier
from utils.source_code import SOURCE_CODE, ARTICLE_SEAT
# import utils.utils as util

SOURCE_DECODE = {v: k for k, v in SOURCE_CODE.items()}
ARTICLE_SEAT_DECODE = {str(v): k for k, v in ARTICLE_SEAT.items()}


class CommuAanlysisMultiQuerier(ElasticSearchQuerier):
    def __init__(self, search_heat_querier):
        super(CommuAanlysisMultiQuerier, self).__init__(None, None, None)
        self.search_heat_querier = search_heat_querier

    def search(self, args):
        keywords = args.get('keywords')
        filters = args.get('filters')
        filters = {} if not filters else filters

        # if len(filters.get('from')) > 0:
        #     filters["from"] = [x for x in filters["from"]]
        field = args.get('field')
        res = []
        for w in keywords:
            a = {"word": w, "filters": filters, 'field': field}
            res.append(self.search_heat_querier.search(a))
        return {"data": res}

    def _build_query(self, args): pass

    def _build_result(self, es_result, param): pass


class CommuAanlysisQuerier(ElasticSearchQuerier):
    def __init__(self, es, index, doc_type):
        super(CommuAanlysisQuerier, self).__init__(es, index, doc_type)

    def _build_query(self, args):
        word = args.get('word')
        filters = args.get('filters')
        field = args.get('field')
        if filters is None:
            filters = dict()
        if word:
            filters['keywords'] = word.split(';')

        query = self._gen_query(filters, field)
        return query, {}, {'keywords': filters['keywords'], 'from': filters.get('from'), 'field': field}

    @staticmethod
    def _build_result(es_result, param):
        agg = es_result['aggregations']
        field = param['field']
        data = extract_from_result(agg, field)

        return {
            'keyword': param['keywords'],
            'res': data}

    def _gen_query(self, filters, field):
        filter_clause = []

        if filters:
            filter_clause = self._add_filter_range_clause(filter_clause, filters, 'publish_timestamp')
            filter_clause = self._add_filter_clause_search(filter_clause, filters.get('keywords', []))
            filter_clause = self._add_filter_clause(filter_clause, filters, 'source')
            filter_clause = self._add_filter_clause(filter_clause, filters, 'from')
            filter_clause = self._add_sentiment_filter_clause(filter_clause, filters, 'full_sentiment_category')

        query = {
            "query": {
                "bool": {
                    "filter": filter_clause
                }
            },
            "aggs": {
                "time_hist": {
                    "date_histogram": {
                        "field": "publish_timestamp",
                        "interval": "1d"
                    },
                    "aggregations": {
                        "user_hist": {
                            "terms": {
                                "field": field,
                                "size": 20
                            }
                        }
                    }
                }
            },
            "size": 0
        }
        return query

    @staticmethod
    def _add_filter_match(must_clause, filters, key):
        if key in filters:
            if filters[key]:
                clause = []
                must_clause.append({
                    'bool': {'should': clause}
                })
                values = filters[key]
                if isinstance(values, str):
                    values = values.split(' ')
                for fk in values:
                    clause.append({'match': {key: {'query': fk, 'minimum_should_match': '10<85% 20<10'}}})
        return must_clause

    @staticmethod
    def _add_filter_clause_search(filter_clause, keywords, search_text=False):
        clause = []
        filter_clause.append({
            'bool': {
                'should': clause,
                'minimum_should_match': 1
            }
        })
        for fk in keywords:
            clause.append({'term': {'keywords': fk}})
            clause.append({'match_phrase': {"title": {"query": fk}}})
            if search_text:
                clause.append({'match_phrase': {"text": {"query": fk}}})
        return filter_clause

    @staticmethod
    def _add_filter_clause(filter_clause, filters, key, cond='must'):
        if key in filters:
            if filters[key]:
                clause = []
                filter_clause.append({
                    'bool': {
                        cond: clause
                    }
                })
                for fk in filters[key]:
                    clause.append({'term': {key: fk}})
        return filter_clause

    @staticmethod
    def _add_sentiment_filter_clause(filter_clause, filters, key):
        if key in filters:
            if filters[key] == [1]:
                clause = []
                filter_clause.append({
                    'bool': {
                        'should': clause
                    }
                })
                for fk in [1, 2]:
                    clause.append({'term': {key: fk}})
            elif filters[key] == [5]:
                clause = []
                filter_clause.append({
                    'bool': {
                        'should': clause
                    }
                })
                for fk in [4, 5]:
                    clause.append({'term': {key: fk}})
            else:
                clause = []
                filter_clause.append({
                    'bool': {
                        'must': clause
                    }
                })
                for fk in filters[key]:
                    clause.append({'term': {key: fk}})
        return filter_clause

    @staticmethod
    def _add_filter_range_clause(filter_clause, filters, key):
        if key in filters:
            if filters[key]:
                clause = []
                filter_clause.append({
                    'bool': {
                        'must': clause
                    }
                })
                fk = filters[key]
                if not isinstance(fk, list) or len(fk) < 1:
                    pass
                else:
                    min_fk = fk[0]
                    if len(fk) >= 2:
                        max_fk = fk[1]
                    else:
                        max_fk = None
                    if min_fk is not None and min_fk != 'null':
                        clause.append({'range': {key: {"gte": min_fk}}})
                    if max_fk is not None and max_fk != 'null':
                        clause.append({'range': {key: {"lte": max_fk}}})
        return filter_clause


def extract_from_result(agg, field):
    buckets = agg['time_hist']['buckets']
    date_list = []
    all_count_list = []
    doc_count_list = []
    source_list = []
    if field == 'from':
        for b in buckets:
            date = b['key_as_string']
            date_list.append(date)
            all_count = b['doc_count']
            all_count_list.append(all_count)
            source_detail = b['user_hist']['buckets']
            from_list = []
            doc_count = []
            for dic in source_detail:
                from_list.append(SOURCE_DECODE.get(dic['key'], '未知'))
                doc_count.append((dic['doc_count']))
            source_list.append(from_list)
            doc_count_list.append(doc_count)

        key = set([k for sub_list in source_list for k in sub_list])
        dic_list = [dict(zip(s, c)) for s, c in zip(source_list, doc_count_list)]
        kv = {}
        for k in key:
            kv[str(k)] = [d.get(k, 0) for d in dic_list]
            kv[str(k)+'_总数量'] = sum([d.get(k, 0) for d in dic_list])
        kv['date'] = date_list
        kv['all_count'] = all_count_list
        return kv
    elif field == 'idx':
        for b in buckets:
            date = b['key_as_string']
            date_list.append(date)
            all_count = b['doc_count']
            all_count_list.append(all_count)
            source_detail = b['user_hist']['buckets']
            from_list = []
            doc_count = []
            for dic in source_detail:
                from_list.append(ARTICLE_SEAT_DECODE.get(dic['key'], '八条+'))
                doc_count.append((dic['doc_count']))
            source_list.append(from_list)
            doc_count_list.append(doc_count)

        key = set([k for sub_list in source_list for k in sub_list])
        dic_list = [dict(zip(s, c)) for s, c in zip(source_list, doc_count_list)]
        kv = {}
        for k in key:
            kv[str(k)] = sum([d.get(k, 0) for d in dic_list])
        kv['date'] = date_list
        kv['all_count'] = all_count_list
        return kv
    else:
        for b in buckets:
            date = b['key_as_string']
            date_list.append(date)
            all_count = b['doc_count']
            all_count_list.append(all_count)
            source_detail = b['user_hist']['buckets']
            from_list = []
            doc_count = []
            for dic in source_detail:
                from_list.append(dic['key'])
                doc_count.append((dic['doc_count']))
            source_list.append(from_list)
            doc_count_list.append(doc_count)

        key = list(set([k for sub_list in source_list for k in sub_list]))
        dic_list = [dict(zip(s, c)) for s, c in zip(source_list, doc_count_list)]
        kv = {}
        count_list = []
        for k in key:
            count_list.append(sum([d.get(k, 0) for d in dic_list]))
        kv['biz_list'] = [k[0] for k in sorted(dict(zip(key, count_list)).items(), key=lambda s: s[1], reverse=True)]
        kv['biz_doc'] = [k[1] for k in sorted(dict(zip(key, count_list)).items(), key=lambda s: s[1], reverse=True)]
        kv['date'] = date_list
        kv['all_count'] = all_count_list
        return kv


# def extract_result(agg):
#     buckets = agg['time_hist']['buckets']
#     date_list = []
#     all_count_list = []
#     doc_count_list = []
#     source_list = []
#     for b in buckets:
#         date = b['key_as_string']
#         date_list.append(date)
#         all_count = b['doc_count']
#         all_count_list.append(all_count)
#         source_detail = b['user_hist']['buckets']
#         from_list = []
#         doc_count = []
#
#         for dic in source_detail:
#             from_list.append(dic['key'])
#             doc_count.append((dic['doc_count']))
#         source_list.append(from_list)
#         doc_count_list.append(doc_count)
#
#     kv = {'date': date_list, 'all_count': all_count_list, 'from': source_list, 'doc_count': doc_count_list}
#     return kv
